<template>
  <view class="chat-container">
    <!-- 公共组件-每个页面必须引入 -->
    <public-module></public-module>

    <!-- 头部 -->
    <view class="chat-header">
      <view class="icon" @click="handleShowBroadside">
        <u-icon name="file-text" color="#1ABC9C" size="30"></u-icon>
      </view>
      <view class="subtitle">我可以帮您搜索、答疑、有关酒类知识。请把你的任务交给我吧~</view>
    </view>

    <!-- 聊天内容区域 -->
    <scroll-view
        class="chat-content"
        scroll-y
        :scroll-top="scrollTop"
        :scroll-with-animation="true"
        @scrolltoupper="loadMoreMessages"
        ref="chatScroll"
    >
      <!-- 欢迎消息 -->
      <view class="welcome-message" v-if="messages.length === 0">
        <u--image
            class="ai-avatar"
            width="120rpx"
            height="120rpx"
            :src="getImg('ai/ai_avatar.png')"
            mode="aspectFit"
        ></u--image>
        <view class="welcome-text">嗨！我是AI助手</view>
      </view>

      <!-- 消息列表 -->
      <view class="message-list">
        <view
            class="message-item"
            :class="item.role === 'user' ? 'user-message' : 'ai-message'"
            v-for="(item, index) in messages"
            :key="index"
        >
          <!-- 用户消息 -->
          <template v-if="item.role === 'user'">
            <view class="message-content user-content">
              <text>{{ item.content }}</text>
            </view>
            <view class="avatar-container">
              <u-avatar size="80rpx" :src="userInfo.headImage || userInfo.memberNumber"></u-avatar>
            </view>
          </template>

          <!-- AI消息 -->
          <template v-else>
            <view class="avatar-container">
              <u--image
                  class="ai-avatar"
                  width="80rpx"
                  height="80rpx"
                  :src="getImg('ai/ai_avatar.png')"
                  mode="aspectFit"
              ></u--image>
            </view>
            <view class="message-content ai-content">
              <view v-if="item.isLoading" class="typing-indicator">
                <view class="dot"></view>
                <view class="dot"></view>
                <view class="dot"></view>
              </view>
              <template v-if="!item.content.includes('</think>')&&!item.isLoading">
                <view class="thinking-part">
                  <view class="typing-indicator" style="margin-left:26rpx">
                    思考中
                    <view class="dot"></view>
                    <view class="dot"></view>
                    <view class="dot"></view>
                  </view>
                  <zero-markdown-view :markdown="item.content"></zero-markdown-view>
                </view>
              </template>
              <template v-if="item.content.includes('</think>')&&!item.isLoading">
                <view class="thinking-part">
                  <view v-if="isStreaming" class="typing-indicator" style="margin-left:26rpx">
                    思考中
                    <view class="dot"></view>
                    <view class="dot"></view>
                    <view class="dot"></view>
                  </view>
                  <zero-markdown-view :markdown="item.content.split('<\/think>')[0]"></zero-markdown-view>
                </view>
                <zero-markdown-view :markdown="item.content.split('</think>')[1]"></zero-markdown-view>
              </template>
            </view>
          </template>
        </view>
      </view>
    </scroll-view>

    <!-- 底部输入区域 -->
    <view class="chat-footer">
      <view class="input-container">
        <u--textarea
            v-model="inputMessage"
            placeholder="请输入您的问题..."
            :autoHeight="true"
            :maxlength="-1"
            :confirmType="'send'"
            @confirm="sendMessage"
        ></u--textarea>
        <view class="action-buttons">
          <!--          <view class="action-item" @click="showFunctionPanel = !showFunctionPanel">
                      <u-icon name="plus-circle" size="50rpx" color="#0E9C98"></u-icon>
                    </view>-->
          <view class="action-item send-btn" @click="sendMessage">
            <u-icon name="arrow-upward" size="50rpx" color="#fff"></u-icon>
          </view>
        </view>
      </view>

      <!-- 功能面板 -->
      <view class="function-panel" v-if="showFunctionPanel">
        <view class="function-item" @click="useFunction('search')">
          <u--image
              width="80rpx"
              height="80rpx"
              :src="getImg('ai/search_icon.png')"
              mode="aspectFit"
          ></u--image>
          <text>联网搜索</text>
        </view>
        <view class="function-item" @click="useFunction('thinking')">
          <u--image
              width="80rpx"
              height="80rpx"
              :src="getImg('ai/thinking_icon.png')"
              mode="aspectFit"
          ></u--image>
          <text>深度思考</text>
        </view>
      </view>
    </view>
    <broadside @newSession="handleNewSession" @select="handleSelect" :apiUrl="apiUrl" :apiKey="apiKey" :chatId="chatId"
               v-if="showBroadside"
               :show.sync="showBroadside" @close="showBroadside = false"></broadside>
  </view>
</template>

<script>
import {mapState} from "vuex";
import baseUrl from "@/config/baseUrl";
import {fetchEventSource} from "@microsoft/fetch-event-source";
//import marked from 'marked';
import broadside from "@/components/module/broadside.vue";

export default {
  components: {
    broadside,
  },
  data() {
    return {
      showBroadside: false,
      socketTask: {},
      inputMessage: "",
      messages: [],
      isConnected: false,
      currentStreamingMessage: "",
      scrollTop: 0,
      showFunctionPanel: false,
      reconnectCount: 0,
      maxReconnectCount: 3,
      reconnectTimer: null,
      isStreaming: false,
      apiKey: "ragflow-FlNGNhZjVlMGVjNDExZjA5MDRlZWExN2",
      apiUrl: "http://175.178.238.5:8011",
      chatId: "2187a61a0ec811f09bebea17b84a9d2b",
      requestTask: null,
      sessionId: "", // 新增会话ID
    };
  },
  computed: {
    ...mapState(["userInfo"]),
  },
  onLoad() {
    console.log(this.generateUUID())
    console.log(this.userInfo)

  },
  onShow() {
    if (!this.isConnected) {
      // this.connectWebSocket();
    }
  },
  onUnload() {

  },
  onHide() {
    // 页面隐藏时不断开连接，保持会话
  },
  methods: {

    handleShowBroadside() {
      this.showBroadside = true;
    },
    handleNewSession() {
      this.sessionId = "";
      this.messages = [];
    },
    handleSelect(e) {
      console.log(e)
      let msg = e.messages;
      msg.shift();
      this.messages = msg;
      this.sessionId = e.id;
    },
    // 创建会话
    async createSession(name) {
      try {
        const response = await uni.request({
          url: `${this.apiUrl}/api/v1/chats/2187a61a0ec811f09bebea17b84a9d2b/sessions`,
          method: 'POST',
          header: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${this.apiKey}`
          },
          data: {
            name: name || '用户会话',
            user_id: this.userInfo.id || ''
          }
        });
        if (response[1].statusCode === 200) {
          this.sessionId = response[1].data.data.id; // 假设返回数据中有session_id
          console.log('会话创建成功:', this.sessionId);
          /*   this.messages.push({
               role: 'assistant',
               content: response[1].data.data.messages[0].content,
               isLoading: false
             });*/
        } else {
          console.error('会话创建失败:', response[0]);
        }
      } catch (error) {
        console.error('创建会话出错:', error);
      }
    },
    getImg(path) {
      return this.$base.ossUrl1 + path;
    },

    // 发送消息
    async sendMessage() {
      if (!this.userInfo.token) {
        uni.showModal({
          title: "操作提示",
          content: "此操作需要登录，请先登录！",
          confirmText: "去登录",
          cancelText: "再逛会",
          confirmColor: "#21ACA8",
          cancelColor: "#999999",
          success: (res) => {
            if (res.confirm) {
              uni.navigateTo({
                url: "/pages/user/login"
              });
            }
          }
        });
        return false;
      }
      if (!this.inputMessage.trim()) {
        uni.showToast({
          title: '请输入问题',
          icon: 'none'
        });
        return;
      }


      // 添加用户消息
      this.messages.push({
        type: "text",
        role: 'user',
        content: this.inputMessage,
        timestamp: Date.now()
      });

      // 添加AI正在输入的消息
      this.messages.push({
        role: 'assistant',
        content: '',
        isLoading: true
      });
      if (!this.sessionId) {
        await this.createSession(this.inputMessage); // 页面加载时创建会话
      }
      // 发送消息到WebSocket
      // #ifdef H5
      fetchEventSource(`${this.apiUrl}/api/v1/chats/2187a61a0ec811f09bebea17b84a9d2b/completions`, {
        method: 'POST',
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${this.apiKey}`,
        },
        body: JSON.stringify({
          question: this.inputMessage,
          stream: true,
          session_id: this.sessionId,
          user_id: this.userInfo.id || ''
        }),
        onopen: (response) => {
          if (response.ok) console.log('连接成功');
          else throw new Error('连接失败');
        },
        onmessage: (event) => {
          let data = JSON.parse(event.data);
          if (data.data.answer) {
            this.isStreaming = true;
            const lastMessage = this.messages[this.messages.length - 1]
            lastMessage.content = data.data.answer; //+= data.choices[0].delta.content || '';
            lastMessage.isLoading = false;
            this.scrollToBottom();

          } else {
            this.isStreaming = false;
          }
        },
        onerror: (err) => {
          console.error('流错误:', err);
        }
      });
      // #endif
      // #ifndef H5

      // #endif

      // #ifdef MP-WEIXIN
      this.requestTask = uni.request({
        url: `${this.apiUrl}/api/v1/chats/2187a61a0ec811f09bebea17b84a9d2b/completions`,
        method: 'POST',
        header: {
          "Content-Type": "application/json",
          "Authorization": `Bearer ${this.apiKey}`
        },
        enableChunked: true,
        data: {
          question: this.inputMessage,
          stream: true, // 小程序不支持流式响应
          session_id: this.sessionId,
          user_id: this.userInfo.id || ''
        },
        success: (res) => {
          console.log(res)

        },
        fail: (err) => {
          console.error('请求失败:', err);
          uni.showToast({
            title: '请求失败',
            icon: 'none'
          });
        },
        complete: () => {
          this.isStreaming = false;
        }
      });
      this.requestTask.onChunkReceived((res) => {
        this.handleChunkData(res.data); // 自定义处理数据块的函数
      });


      // #endif

      // 清空输入框
      this.inputMessage = '';
    },
    handleChunkData(arrayBuffer) {
      // 兼容处理：真机需用 arrayBufferToBase64，开发工具可能直接返回字符串
      const uint8Array = new Uint8Array(arrayBuffer);
      const base64Data = uni.arrayBufferToBase64(uint8Array);
      const decodedData = new Buffer(base64Data, 'base64').toString('utf8');

      // 按 SSE 格式分割数据块
      const lines = decodedData.split('\n\n');

      lines.forEach(line => {
        if (line.startsWith('data:')) {
          const eventData = line.substring(5).trim();
          let res = JSON.parse(eventData);
          if (res.code === 0) {
            const lastMessage = this.messages[this.messages.length - 1];
            this.isStreaming = true;
            if (res.data.answer)
              lastMessage.content = res.data.answer;
            else {
              this.isStreaming = false;
            }
            lastMessage.isLoading = false;
            this.scrollToBottom();
          }

        }
      });
    },
    // 使用特定功能
    useFunction(type) {
      this.showFunctionPanel = false;

      let prefix = '';
      if (type === 'search') {
        prefix = '请帮我搜索：';
      } else if (type === 'thinking') {
        prefix = '请深入思考：';
      }

      this.inputMessage = prefix + this.inputMessage;
    },

    // 滚动到底部
    scrollToBottom() {
      this.$nextTick(() => {
        const query = uni.createSelectorQuery().in(this);
        query.select('.chat-content').boundingClientRect();
        query.selectAll('.message-item').boundingClientRect();
        query.exec((res) => {
          if (res && res[0] && res[1]) {
            // 计算所有消息的总高度
            const totalHeight = res[1].reduce((sum, item) => sum + item.height, 0);
            // 设置scrollTop为内容高度减去可视区域高度
            this.scrollTop = totalHeight - res[0].height + 60;
          }
        });
      });
    },

    // 加载更多历史消息
    loadMoreMessages() {
      // 这里可以实现加载更多历史消息的逻辑
      console.log('加载更多历史消息');
    },
    generateUUID() {
      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
      });
    }
  }
}
</script>
<style lang="scss" scoped>
.chat-container {
  display: flex;
  flex-direction: column;
  height: 95vh;
  background-color: #f8f8f8;
}

.chat-header {

  display: flex;
  padding: 40rpx 30rpx;
  /* #ifdef H5 */
  padding-top: 40rpx;
  /* #endif */
  /* #ifdef MP */
  padding-top: 40rpx;
  /* #endif */
  /* #ifdef APP-PLUS */
  padding-top: 100rpx;
  /* #endif */
  background: linear-gradient(to right, #eafffe, #f4f5f5);
  text-align: center;

  .title {
    font-size: 36rpx;
    font-weight: bold;
    color: #333;
    margin-bottom: 10rpx;
  }

  .subtitle {
    font-size: 28rpx;
    color: #666;
  }
}

.chat-content {
  flex: 1;
  padding: 20rpx;
  overflow-y: auto;
  height: 1px; // 添加这个确保flex布局下滚动区域正常工作

  .welcome-message {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 60rpx 0;

    .ai-avatar {
      margin-bottom: 30rpx;
    }

    .welcome-text {
      font-size: 32rpx;
      color: #333;
      font-weight: bold;
    }
  }

  .message-list {
    padding-bottom: 20rpx;
  }

  .message-item {
    display: flex;
    margin-bottom: 30rpx;

    &.user-message {
      flex-direction: row-reverse;
    }

    .avatar-container {
      width: 80rpx;
      height: 80rpx;
      flex-shrink: 0;
    }

    .message-content {
      max-width: 70%;
      padding: 20rpx;
      border-radius: 12rpx;
      margin: 0 20rpx;
      word-break: break-word;

      &.user-content {
        background-color: #0E9C98;
        color: #fff;
        border-top-right-radius: 0;
      }

      &.ai-content {
        background-color: #fff;
        color: #333;
        border-top-left-radius: 0;
        box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
      }
    }
  }
}

.chat-footer {
  padding: 20rpx;
  background-color: #fff;
  border-top: 1px solid #eee;

  .input-container {
    display: flex;
    align-items: flex-end;

    /deep/ .u-textarea {
      flex: 1;
      background-color: #f5f5f5;
      border-radius: 12rpx;
      padding: 20rpx;
      max-height: 200rpx;
      min-height: 80rpx;
    }

    .action-buttons {
      display: flex;
      margin-left: 20rpx;

      .action-item {
        width: 80rpx;
        height: 80rpx;
        display: flex;
        align-items: center;
        justify-content: center;
        margin-left: 10rpx;

        &.send-btn {
          background-color: #0E9C98;
          border-radius: 50%;
        }
      }
    }
  }
}

.function-panel {
  display: flex;
  padding: 30rpx 0;

  .function-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-right: 40rpx;

    text {
      font-size: 24rpx;
      color: #666;
      margin-top: 10rpx;
    }
  }
}


// 打字指示器动画
.typing-indicator {
  display: flex;
  align-items: center;

  .dot {
    width: 10rpx;
    height: 10rpx;
    border-radius: 50%;
    background-color: #999;
    margin: 0 5rpx;
    animation: typing 1.5s infinite ease-in-out;

    &:nth-child(1) {
      animation-delay: 0s;
    }

    &:nth-child(2) {
      animation-delay: 0.2s;
    }

    &:nth-child(3) {
      animation-delay: 0.4s;
    }
  }
}

@keyframes typing {
  0%, 60%, 100% {
    transform: translateY(0);
  }
  30% {
    transform: translateY(-10rpx);
  }
}

// Markdown样式
:deep(.ai-content) {
  line-height: 1.6;

  p {
    margin: 10rpx 0;
  }

  h1, h2, h3, h4, h5, h6 {
    margin: 20rpx 0 10rpx 0;
    font-weight: bold;
  }

  h1 {
    font-size: 36rpx;
  }

  h2 {
    font-size: 32rpx;
  }

  h3 {
    font-size: 30rpx;
  }

  ul, ol {
    padding-left: 40rpx;
    margin: 10rpx 0;
  }

  li {
    margin: 5rpx 0;
  }

  code {
    background-color: #f5f5f5;
    padding: 4rpx 8rpx;
    border-radius: 4rpx;
    font-family: monospace;
    font-size: 28rpx;
  }

  pre {
    background-color: #f5f5f5;
    padding: 20rpx;
    border-radius: 8rpx;
    overflow-x: auto;
    margin: 10rpx 0;

    code {
      background-color: transparent;
      padding: 0;
    }
  }

  blockquote {
    border-left: 4rpx solid #ddd;
    padding-left: 20rpx;
    color: #666;
    margin: 10rpx 0;
  }

  a {
    color: #0E9C98;
    text-decoration: none;
  }

  img {
    max-width: 100%;
    height: auto;
    margin: 10rpx 0;
    border-radius: 8rpx;
  }

  table {
    border-collapse: collapse;
    width: 100%;
    margin: 10rpx 0;

    th, td {
      border: 1px solid #ddd;
      padding: 10rpx;
      text-align: left;
    }

    th {
      background-color: #f5f5f5;
    }
  }
}

// 添加思考部分样式
.thinking-part {
  background-color: #f8f9fa;
  padding: 15rpx;
  border-radius: 8rpx;
  margin-bottom: 15rpx;
  color: #666;
  font-size: 24rpx;
  border-left: 4rpx solid #0E9C98;
}

</style>

